package org.proteored.miapeapi.xml.mzidentml;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.proteored.miapeapi.cv.ControlVocabularyManager;
import org.proteored.miapeapi.cv.msi.AdditionalParameterName;
import org.proteored.miapeapi.cv.msi.SearchType;
import org.proteored.miapeapi.interfaces.Software;
import org.proteored.miapeapi.interfaces.msi.AdditionalParameter;
import org.proteored.miapeapi.interfaces.msi.Database;
import org.proteored.miapeapi.interfaces.msi.InputParameter;
import org.proteored.miapeapi.xml.mzidentml.autogenerated.FilterType;
import org.proteored.miapeapi.xml.mzidentml.autogenerated.FuGECommonOntologyCvParamType;
import org.proteored.miapeapi.xml.mzidentml.autogenerated.FuGECommonOntologyParamType;
import org.proteored.miapeapi.xml.mzidentml.autogenerated.FuGECommonOntologyUserParamType;
import org.proteored.miapeapi.xml.mzidentml.autogenerated.PSIPIAnalysisProcessProteinDetectionProtocolType;
import org.proteored.miapeapi.xml.mzidentml.autogenerated.PSIPIAnalysisSearchEnzymeType;
import org.proteored.miapeapi.xml.mzidentml.autogenerated.PSIPIAnalysisSearchSearchDatabaseType;
import org.proteored.miapeapi.xml.mzidentml.autogenerated.PSIPIAnalysisSearchSearchModificationType;
import org.proteored.miapeapi.xml.mzidentml.autogenerated.PSIPIAnalysisSearchSpectrumIdentificationProtocolType;
import org.proteored.miapeapi.xml.mzidentml.util.MzidentmlControlVocabularyXmlFactory;
import org.proteored.miapeapi.xml.mzidentml.util.Utils;
import org.proteored.miapeapi.xml.util.MiapeXmlUtil;

public class InputParameterImpl implements InputParameter {
	private final PSIPIAnalysisSearchSpectrumIdentificationProtocolType protocol;
	private final PSIPIAnalysisProcessProteinDetectionProtocolType proteinDetectionProtocol;
	private final List<PSIPIAnalysisSearchSearchDatabaseType> searchDatabaseList;
	private final Software msiSoftware;
	private final Integer identifier;
	private final Long numSeqSearched;
	private final ControlVocabularyManager cvManager;

	public InputParameterImpl(
			PSIPIAnalysisSearchSpectrumIdentificationProtocolType spectProtocol,
			PSIPIAnalysisProcessProteinDetectionProtocolType proteinDetectionProtocol,
			List<PSIPIAnalysisSearchSearchDatabaseType> databaseListXML,
			Software msiSoftware, Integer identifier, Long numSeqSearched,
			ControlVocabularyManager cvManager) {
		this.protocol = spectProtocol;
		this.searchDatabaseList = databaseListXML;
		this.msiSoftware = msiSoftware;
		this.identifier = identifier;
		this.numSeqSearched = numSeqSearched;
		this.cvManager = cvManager;
		this.proteinDetectionProtocol = proteinDetectionProtocol;
	}

	@Override
	public String getAaModif() {
		if (protocol.getModificationParams() != null
				&& protocol.getModificationParams().getSearchModification() != null) {
			List<PSIPIAnalysisSearchSearchModificationType> modifications = protocol
					.getModificationParams().getSearchModification();
			StringBuilder sb = new StringBuilder();
			// fix mode if false --> Variable true --> Fixed
			// Add CV

			for (PSIPIAnalysisSearchSearchModificationType modification : modifications) {
				if (!sb.equals(""))
					sb.append(MiapeXmlUtil.TERM_SEPARATOR);
				final String modificationName = MzidentmlControlVocabularyXmlFactory
						.readEntireParam(modification.getModParam()
								.getCvParam());
				if (modificationName != null && !modificationName.equals(""))
					sb.append(modificationName + MiapeXmlUtil.TERM_SEPARATOR);

				if (modification.isFixedMod()) {
					sb.append(Utils.FIXED);
					sb.append(MiapeXmlUtil.TERM_SEPARATOR);
				} else {
					sb.append(Utils.VARIABLE);
					sb.append(MiapeXmlUtil.TERM_SEPARATOR);
				}
				if (modification.getModParam().getMassDelta() != 0) {
					sb.append(Utils.MASS_DELTA + "=");
					sb.append(modification.getModParam().getMassDelta());
					sb.append(MiapeXmlUtil.TERM_SEPARATOR);
				}

				if (modification.getModParam().getResidues().size() > 0) {
					sb.append(Utils.RESIDUES + "=");
					int count = 0;
					for (String residue : modification.getModParam()
							.getResidues()) {
						sb.append(residue);
						count++;
						if (count < modification.getModParam().getResidues()
								.size()) {
							sb.append(", ");
						}
					}
					sb.append(MiapeXmlUtil.TERM_SEPARATOR);
				}
				if (modification.getSpecificityRules() != null) {
					sb.append(MzidentmlControlVocabularyXmlFactory
							.readEntireCVParamList(modification
									.getSpecificityRules().getCvParam(), true));
				}
			}
			return Utils.checkReturnedString(sb);
		}
		return null;
	}

	@Override
	public String getAdditionalCleavages() {
		StringBuilder sb = new StringBuilder();
		if (protocol.getEnzymes() != null
				&& protocol.getEnzymes().getEnzyme() != null) {
			for (PSIPIAnalysisSearchEnzymeType enzyme : protocol.getEnzymes()
					.getEnzyme()) {
				// disabled on 28-Mat-2013: is already captured in
				// getMissedCleavages
				// if (enzyme.getMissedCleavages() != null) {
				// sb.append(Utils.MISSCLEAVAGES + "=" +
				// enzyme.getMissedCleavages()
				// + MiapeXmlUtil.TERM_SEPARATOR);
				// }
				if (enzyme.isSemiSpecific() != null) {
					sb.append(Utils.SEMISPECIFIC + "= true"
							+ MiapeXmlUtil.TERM_SEPARATOR);
				}
				if (enzyme.getNTermGain() != null) {
					sb.append(Utils.NTERM_GAIN + "=" + enzyme.getNTermGain()
							+ MiapeXmlUtil.TERM_SEPARATOR);
				}
				if (enzyme.getCTermGain() != null) {
					sb.append(Utils.CTERM_GAIN + "=" + enzyme.getNTermGain()
							+ MiapeXmlUtil.TERM_SEPARATOR);
				}
				if (enzyme.getMinDistance() != null) {
					sb.append(Utils.MIN_DISTANCE + "="
							+ enzyme.getMinDistance()
							+ MiapeXmlUtil.TERM_SEPARATOR);
				}
			}
		}
		return Utils.checkReturnedString(sb);

	}

	@Override
	public Set<AdditionalParameter> getAdditionalParameters() {
		// from Additional Search Params
		Set<AdditionalParameter> addParameter = new HashSet<AdditionalParameter>();
		if (protocol.getAdditionalSearchParams() != null
				&& protocol.getAdditionalSearchParams().getParamGroup() != null) {
			List<FuGECommonOntologyParamType> parameters = protocol
					.getAdditionalSearchParams().getParamGroup();
			for (FuGECommonOntologyParamType param : parameters) {
				if (param != null) {
					StringBuilder wkName = new StringBuilder();
					StringBuilder wkValue = new StringBuilder();
					if (param.getValue() == null) {
						wkName.append(param.getName());
					} else {
						wkName.append(param.getName());
						wkValue.append(param.getValue());
					}
					if (param.getUnitName() != null) {
						wkValue.append(" " + param.getUnitName());
					}
					addParameter.add(new AdditionalParameterImpl(wkName
							.toString(), wkValue.toString()));
				}
			}
		}
		if (this.proteinDetectionProtocol != null
				&& proteinDetectionProtocol.getAnalysisParams() != null
				&& proteinDetectionProtocol.getAnalysisParams().getParamGroup() != null) {
			List<FuGECommonOntologyParamType> parameters = proteinDetectionProtocol
					.getAnalysisParams().getParamGroup();
			for (FuGECommonOntologyParamType param : parameters) {
				if (param != null) {
					StringBuilder wkName = new StringBuilder();
					StringBuilder wkValue = new StringBuilder();
					if (param.getValue() == null) {
						wkName.append(param.getName());
					} else {
						wkName.append(param.getName());
						wkValue.append(param.getValue());
					}
					if (param.getUnitName() != null) {
						wkValue.append(" " + param.getUnitName());
					}
					addParameter.add(new AdditionalParameterImpl(wkName
							.toString(), wkValue.toString()));
				}
			}
		}
		if (addParameter.size() > 0)
			return addParameter;
		return null;
	}

	@Override
	public String getCleavageName() {
		StringBuilder sb = new StringBuilder();

		if (protocol.getEnzymes() != null
				&& protocol.getEnzymes().getEnzyme() != null) {
			List<PSIPIAnalysisSearchEnzymeType> enzymes = protocol.getEnzymes()
					.getEnzyme();

			int counter = 1;
			for (PSIPIAnalysisSearchEnzymeType enzyme : enzymes) {
				if (enzyme.getEnzymeName() != null)
					sb.append(MzidentmlControlVocabularyXmlFactory
							.readEntireParamList(enzyme.getEnzymeName()));
				if (counter < enzymes.size()) {
					sb.append(MiapeXmlUtil.TERM_SEPARATOR);
					counter++;
				}

			}
		}
		return Utils.checkReturnedString(sb);

	}

	@Override
	public String getCleavageRules() {
		StringBuilder sb = new StringBuilder();
		int counter = 1;
		if (protocol.getEnzymes() != null
				&& protocol.getEnzymes().getEnzyme() != null) {
			for (PSIPIAnalysisSearchEnzymeType enzyme : protocol.getEnzymes()
					.getEnzyme()) {
				if (enzyme.getSiteRegexp() != null) {
					sb.append(Utils.SITEREGEXP + "=");
					sb.append(enzyme.getSiteRegexp());
					if (counter < protocol.getEnzymes().getEnzyme().size()) {
						sb.append(MiapeXmlUtil.TERM_SEPARATOR);
						counter++;
					}

				}
			}
		}
		return Utils.checkReturnedString(sb);

	}

	@Override
	public Set<Database> getDatabases() {
		if (this.searchDatabaseList != null) {
			Set<Database> databaseSet = new HashSet<Database>();
			for (PSIPIAnalysisSearchSearchDatabaseType databaseXML : searchDatabaseList) {
				databaseSet.add(new DatabaseImpl(databaseXML));
			}
			return databaseSet;
		}
		return null;
	}

	@Override
	public String getFragmentMassTolerance() {
		if (protocol.getFragmentTolerance() != null) {
			return MzidentmlControlVocabularyXmlFactory.readEntireCVParamList(
					protocol.getFragmentTolerance().getCvParam(), false);
		}
		return null;
	}

	@Override
	public String getFragmentMassToleranceUnit() {
		if (protocol.getFragmentTolerance() != null) {
			return MzidentmlControlVocabularyXmlFactory
					.readFirstUnitCVParamList(protocol.getFragmentTolerance()
							.getCvParam());
		}
		return null;
	}

	@Override
	public int getId() {
		if (identifier != null) {
			return identifier;
		}
		return -1;
	}

	@Override
	public String getMinScore() {
		if (protocol.getThreshold() != null) {
			return MzidentmlControlVocabularyXmlFactory
					.readEntireParamList(protocol.getThreshold());
		}
		return null;
	}

	@Override
	public String getMisscleavages() {
		if (protocol.getEnzymes() != null
				&& protocol.getEnzymes().getEnzyme() != null) {
			if (protocol.getEnzymes().getEnzyme().get(0).getMissedCleavages() != null) {
				return protocol.getEnzymes().getEnzyme().get(0)
						.getMissedCleavages().toString();
			}
		}
		return null;
	}

	@Override
	public String getName() {
		if (protocol.getName() != null && !protocol.getName().equals(""))
			return protocol.getName();
		return protocol.getId();
	}

	@Override
	public String getNumEntries() {
		if (numSeqSearched != null && numSeqSearched != -1)
			return numSeqSearched.toString();
		return null;
	}

	@Override
	public String getPmfMassTolerance() {
		if (protocol.getSearchType() != null
				&& protocol.getSearchType().getCvParam() != null) {
			if (SearchType
					.getPMFSearchTerm(cvManager)
					.getTermAccession()
					.equals(protocol.getSearchType().getCvParam()
							.getAccession())
					|| SearchType
							.getCombinedPMFMSMSSearchTerm(cvManager)
							.getTermAccession()
							.equals(protocol.getSearchType().getCvParam()
									.getAccession())) {
				return MzidentmlControlVocabularyXmlFactory
						.readEntireCVParamList(protocol.getParentTolerance()
								.getCvParam(), false);
			}
		}
		return null;
	}

	@Override
	public String getPmfMassToleranceUnit() {
		if (protocol.getSearchType() != null
				&& protocol.getSearchType().getCvParam() != null) {
			if (SearchType
					.getPMFSearchTerm(cvManager)
					.getTermAccession()
					.equals(protocol.getSearchType().getCvParam()
							.getAccession())
					|| SearchType
							.getCombinedPMFMSMSSearchTerm(cvManager)
							.getTermAccession()
							.equals(protocol.getSearchType().getCvParam()
									.getAccession())) {
				return MzidentmlControlVocabularyXmlFactory
						.readFirstUnitCVParamList(protocol.getParentTolerance()
								.getCvParam());
			}
		}
		return null;
	}

	@Override
	public String getPrecursorMassTolerance() {
		if (protocol.getParentTolerance() != null) {
			return MzidentmlControlVocabularyXmlFactory.readEntireCVParamList(
					protocol.getParentTolerance().getCvParam(), false);
		}
		return null;
	}

	@Override
	public String getPrecursorMassToleranceUnit() {
		if (protocol.getParentTolerance() != null) {
			return MzidentmlControlVocabularyXmlFactory
					.readFirstUnitCVParamList(protocol.getParentTolerance()
							.getCvParam());
		}
		return null;
	}

	@Override
	public String getScoringAlgorithm() {

		if (this.protocol.getAdditionalSearchParams() != null) {
			for (FuGECommonOntologyParamType paramType : this.protocol
					.getAdditionalSearchParams().getParamGroup()) {
				// take <userParam name="Mascot Instrument Name"
				// value="MALDI-TOF-TOF"/>
				if (paramType instanceof FuGECommonOntologyUserParamType) {
					if (paramType
							.getName()
							.equals(MzidentmlControlVocabularyXmlFactory.MASCOT_INSTRUMENT_NAME)) {
						return MzidentmlControlVocabularyXmlFactory
								.readEntireParam(paramType);
					}
				}
				// take ("MS:1001376", "Phenyx:Scoring Model")
				if (paramType instanceof FuGECommonOntologyCvParamType) {
					if (((FuGECommonOntologyCvParamType) paramType)
							.getAccession()
							.equals(AdditionalParameterName
									.getInstance(cvManager)
									.getCVTermByAccession(
											AdditionalParameterName.PHENYX_SCORING_MODEL)
									.getTermAccession())) {
						return MzidentmlControlVocabularyXmlFactory
								.readEntireParam(paramType);
					}
				}
			}
		}
		return null;
	}

	@Override
	public String getSearchType() {
		if (protocol.getSearchType() != null)
			return MzidentmlControlVocabularyXmlFactory
					.readEntireParam(protocol.getSearchType());
		return null;
	}

	@Override
	public Software getSoftware() {
		return msiSoftware;
	}

	@Override
	public String getTaxonomy() {
		StringBuilder sb = new StringBuilder();
		if (protocol.getDatabaseFilters() == null)
			return null;
		List<FilterType> filters = protocol.getDatabaseFilters().getFilter();
		for (FilterType filterType : filters) {
			if (filterType.getFilterType() != null) {
				sb.append(Utils.FILTER_TYPE + "=");
				sb.append(MzidentmlControlVocabularyXmlFactory
						.readEntireParam(filterType.getFilterType()));
				sb.append(MiapeXmlUtil.TERM_SEPARATOR);
			}

			if (filterType.getExclude() != null) {
				sb.append(Utils.EXCLUDE + "=");
				sb.append(MzidentmlControlVocabularyXmlFactory
						.readEntireParamList(filterType.getExclude()));
				sb.append(MiapeXmlUtil.TERM_SEPARATOR);
			}
			if (filterType.getInclude() != null) {
				sb.append(Utils.INCLUDE + "=");
				sb.append(MzidentmlControlVocabularyXmlFactory
						.readEntireParamList(filterType.getInclude()));
				sb.append(MiapeXmlUtil.TERM_SEPARATOR);
			}
		}

		return Utils.checkReturnedString(sb);

	}

}
